/**
 * Copyright (C) 2022-2023
 * All rights reserved, Designed By www.tonetn.com
 * 注意：
 * 本软件为www.tonetn.com开发研制，未经购买不得使用
 * 购买后可获得全部源代码（禁止转卖、分享、上传到码云、github等开源平台）
 * 一经发现盗用、分享等行为，将追究法律责任，后果自负
 */
package com.xunyin.modules.device.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.xunyin.cache.TokenCache;
import com.xunyin.common.service.impl.BaseServiceImpl;
import com.xunyin.common.utils.QueryHelpPlus;
import com.xunyin.enums.ErrorEnum;
import com.xunyin.modules.device.domain.TDevice;
import com.xunyin.modules.device.domain.TDeviceLog;
import com.xunyin.modules.device.service.TDeviceService;
import com.xunyin.modules.device.service.dto.TDeviceDto;
import com.xunyin.modules.device.service.dto.TDeviceQueryCriteria;
import com.xunyin.modules.device.service.mapper.TDeviceLogMapper;
import com.xunyin.modules.device.service.mapper.TDeviceMapper;
import com.xunyin.modules.shareorder.domain.TShareOrder;
import com.xunyin.modules.shareorder.service.mapper.TShareOrderMapper;
import com.xunyin.nettyV.client.PubMsg;
import com.xunyin.schedule.RequestSignUtils;
import com.xunyin.utils.RequestTtlockUtils;
import com.xunyin.utils.SignUtil;
import com.xunyin.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;


/**
 * @author admin
 * @date 2022-10-15
 */
@Service
@RequiredArgsConstructor
@Slf4j
//@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class TDeviceServiceImpl extends BaseServiceImpl<TDeviceMapper, TDevice> implements TDeviceService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private TShareOrderMapper tShareOrderMapper;

    @Autowired
    private TDeviceMapper tDeviceMapper;

    @Autowired
    private TDeviceLogMapper tDeviceLogMapper;

    @Value("${tuya.url}")
    private String tuyaUrl;

    @Value("${tuya.client_id}")
    private String tuyaClientId;

    @Value("${tuya.client_secret}")
    private String tuyaClientSecret;

    @Override
    //@Cacheable
    public Map<String, Object> queryAll(TDeviceQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        PageInfo<TDevice> page = new PageInfo<>(queryAll(criteria));
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", page.getList());
        map.put("totalElements", page.getTotal());
        return map;
    }


    @Override
    //@Cacheable
    public List<TDevice> queryAll(TDeviceQueryCriteria criteria) {
        return baseMapper.selectList(QueryHelpPlus.getPredicate(TDevice.class, criteria));
    }

    /**
     * 根据门店id -所有茶室的门禁设备
     * @param storeId  这传进来参数为空，表示只查询包间的房门或电源设备
     * @param storeRoomId 这传进来参数为空，表示查询该门店下所有包间的房门或电源设备
     *
     * @return
     */
    @Override
    public List<TDevice> getDeviceListByStoreRoomIdOrStoreId(Integer storeId, Integer storeRoomId, Integer deviceTypeFlag) throws IOException {

        JSONObject keyCache = new JSONObject();
        LambdaQueryWrapper<TDevice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TDevice::getStatus, 1)
                .eq(TDevice::getDeviceStatus, 1);
        // 只查询门店的大门设备
        if (deviceTypeFlag == 0) {
            wrapper.and(i -> i.eq(TDevice::getDeviceType, 0));
            // 只查询包间的房门设备
        } else if (deviceTypeFlag == 1) {
            wrapper.and(i -> i.eq(TDevice::getDeviceType, 1));
            // 只查询包间的电源设备
        } else if (deviceTypeFlag == 2) {
            wrapper.and(i -> i.eq(TDevice::getDeviceType, 2));
            // 只查询包间的音箱喇叭设备
        } else if (deviceTypeFlag == 3) {
            wrapper.and(i -> i.eq(TDevice::getDeviceType, 3));
            // 查询自研设备包含（门锁、电源、喇叭）三个一控制
        } else if (deviceTypeFlag == 4) {
            wrapper.and(i -> i.eq(TDevice::getDeviceType, 4));
            // 查询智能插座(Aqara)
        }else if(deviceTypeFlag == 6){
            wrapper.and(i -> i.eq(TDevice::getDeviceType, 6));
            // 查询第三方硬件方案,涂鸦设备包间的房门设备与电源设备,第三方硬件通通锁
        } else {

            wrapper.and(i -> i.eq(TDevice::getDeviceType, 1)
                    .or().eq(TDevice::getDeviceType, 2)
                    .or().eq(TDevice::getDeviceType, 3)
                    .or().eq(TDevice::getDeviceType, 5));
        }

        if (storeId != null) {
            wrapper.eq(TDevice::getStoreId, storeId);
        }
        if (storeRoomId != null) {
            wrapper.eq(TDevice::getStoreRoomId, storeRoomId);
        }

        List<TDevice> devices = baseMapper.selectList(wrapper);
        List<TDevice> resList = new ArrayList();
        for (TDevice device : devices) {
            if (device.getDeviceType() != null && !keyCache.containsKey(device.getDeviceNo())) {

                keyCache.put(device.getDeviceNo(), true);
                resList.add(device);

            }
        }
        return resList;
        //JSONObject json = new JSONObject();
        //json.put("doorDevices", resList);
        //return CommonUtil.successJson(json);
    }


    /**
     * 根据门店id -所有茶室的门禁复位
     * @param storeId
     * @return
     */
    @Override
    public Boolean doorResetByStoreIdProg1(Integer storeId) {
        JSONObject keyCache = new JSONObject();
        LambdaQueryWrapper<TDevice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TDevice::getStoreId, storeId)
                .eq(TDevice::getDeviceType, 4)
                .eq(TDevice::getDeviceStatus, 1);
        List<TDevice> devices = baseMapper.selectList(wrapper);
        Boolean allSuccess = true;
        for (TDevice device : devices) {
            if (device.getDeviceType() != null && !keyCache.containsKey(device.getMacAddr())) {
                keyCache.put(device.getMacAddr(), true);
                Boolean res = sendCommand(device, 2, 1);
                if (!res) {
                    allSuccess = false;
                }
            }
        }
        return allSuccess;
    }

    /**
     * 根据门店id -所有茶室的门禁复位
     * @param storeId
     * @return
     */
    @Override
    public Boolean doorResetByStoreId(Integer storeId) throws Exception {

        JSONObject keyCache = new JSONObject();
        LambdaQueryWrapper<TDevice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TDevice::getStoreId, storeId)
                .eq(TDevice::getStatus, 1)
                .eq(TDevice::getDeviceType, 1)
                .eq(TDevice::getDeviceStatus, 1);
        List<TDevice> devices = baseMapper.selectList(wrapper);

        List resList = new ArrayList();
        Boolean allSuccess = true;
        for (TDevice device : devices) {
            if (device.getDeviceType() != null && !keyCache.containsKey(device.getDeviceNo())) {

                keyCache.put(device.getDeviceNo(), true);
                Boolean res = true;
                if(device.getDeviceType()==5){

                    res =  RequestTtlockUtils.executeUnlock(device.getDeviceNo());

                }else{
                    res = sendCommand(device, "true");
                }

                if (!res) {
                    allSuccess = false;
                }
            }
        }
        return allSuccess;
    }

    /**
     * 远程开门
     * 自研硬件方案
     * @param doorDeviceId
     * @return
     */
    @Override
    public String remoteOpenDoorProg1(Integer doorDeviceId) throws Exception {

        if (doorDeviceId == null) {
            return ErrorEnum.E_90004.getErrorMsg();
        }
        // 根据设备Id获取设备信息
        TDevice device = tDeviceMapper.selectById(doorDeviceId);
        if(device!=null){

            // 表示用通通锁
            if(device.getDeviceType()==5){

                Boolean result = RequestTtlockUtils.executeUnlock(device.getDeviceNo());
                if(result){
                    return "success";
                }

            }else{

                Boolean res = sendCommand(device, 2, 1);
                if (res) {
                    return "success";
                } else {
                    return ErrorEnum.E_100025.getErrorCode();
                }

            }
        }else{

            return ErrorEnum.E_100030.getErrorCode();
        }
        return ErrorEnum.E_100030.getErrorCode();


/*        if (device.getDeviceType() == 4) {  // device.getDoorType() == 2
            int count = tShareOrderMapper.checkStoreRoomOrderInServer(device.getStoreRoomId());
            if (count > 0) {
                log.error("茶室使用中,茶室={}", device.getDeviceName());
                return ErrorEnum.E_100021.getErrorMsg();
            }
        }*/

        //sendCommand(device, 2, 1);

/*        try{

            Boolean res = sendCommand(device,2, 0);
            if(res){
                Thread thread = new Thread(new Runnable() {
                    @SneakyThrows
                    @Override
                    public void run() {
                        Thread.sleep(1000);
                        sendCommand(device,2, 1);
                    }
                });
                thread.start();
            }else{
                return ErrorEnum.E_100025.getErrorCode();
            }

        }catch (Exception e) {
            log.error("开门失败,茶室={}", device.getDeviceName());
            return ErrorEnum.E_100020.getErrorCode();
        }*/
        //return "success";
    }

    /**
     * 远程开门
     * @param doorDeviceId
     * @return
     */
    @Override
    public String remoteOpenDoor(Integer doorDeviceId) {

        if (doorDeviceId == null) {
            return ErrorEnum.E_90004.getErrorMsg();
        }
        // 根据设备Id获取设备信息
        TDevice device = tDeviceMapper.selectById(doorDeviceId);
        if (device.getDeviceType() == 1) {  // device.getDoorType() == 2
            int count = tShareOrderMapper.checkStoreRoomOrderInServer(device.getStoreRoomId());
            if (count > 0) {
                log.error("茶室使用中,茶室={}", device.getDeviceName());
                return ErrorEnum.E_100021.getErrorMsg();
            }
        }

        try {

            // 表示用通通锁
            if(device.getDeviceType()==5) {

                Boolean result = RequestTtlockUtils.executeUnlock(device.getDeviceNo());
                if(result){
                    return "success";
                }

            }else{

                if (sendCommand(device, "false")) {
                    Thread thread = new Thread(new Runnable() {
                        @SneakyThrows
                        @Override
                        public void run() {
                            Thread.sleep(1000);
                            sendCommand(device, "true");
                        }
                    });
                    thread.start();

                } else {
                    return ErrorEnum.E_100025.getErrorCode();
                }

            }

        } catch (Exception e) {
            log.error("开门失败,茶室={}", device.getDeviceName());
            return ErrorEnum.E_100020.getErrorCode();
        }
        return "success";
    }

    /**
     * 门店管理员开门
     *
     */
    @Override
    public String adminOpenDoor(String hardwareProg, Integer storeId, Integer storeRoomId, Integer deviceType) throws Exception {
        LambdaQueryWrapper<TDevice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TDevice::getStatus, 1).eq(TDevice::getDeviceStatus, 1);
        if (storeId != 0) {
            wrapper.eq(TDevice::getStoreId, storeId);
        }
        //if (storeRoomId != 0) {
            wrapper.eq(TDevice::getStoreRoomId, storeRoomId);
        //}
        //if (deviceType != null) {

        //}

/*        // 自研硬件方案
        if (hardwareProg.equals("1")) {

            wrapper.eq(TDevice::getDeviceType, 4);

        // 第三方硬件方案（涂鸦、通通锁）
        }else {

            wrapper.eq(TDevice::getDeviceType, deviceType);
        }*/
        //wrapper.eq(TDevice::getDeviceType, deviceType);

        List<TDevice> devices = baseMapper.selectList(wrapper);

        if(devices!=null){
            for(TDevice device :devices){

                // 自研硬件方案
                if (hardwareProg.equals("1")) {

/*                    Boolean res = sendCommand(device, 2, 1);
                    if (res) {
                        return "success";
                    } else {
                        return ErrorEnum.E_100025.getErrorCode();
                    }*/

                    // 表示用通通锁
                    if(device.getDeviceType()==5){

                        Boolean result = RequestTtlockUtils.executeUnlock(device.getDeviceNo());
                        if(result){
                            return "success";
                        }

                    }else{

                        Boolean res = sendCommand(device, 2, 1);
                        if (res) {
                            return "success";
                        } else {
                            return ErrorEnum.E_100025.getErrorCode();
                        }

                    }

                // 第三方硬件方案（涂鸦、通通锁）
                } else {

                    // 表示用通通锁
                    if(device.getDeviceType()==5){

                        Boolean result = RequestTtlockUtils.executeUnlock(device.getDeviceNo());
                        if(result){
                            return "success";
                        }
                    // 表示用涂鸦通断器控制磁力锁与电插锁
                    }else{


                        if (sendCommand(device, "false")) {
                            Thread thread = new Thread(new Runnable() {
                                @SneakyThrows
                                @Override
                                public void run() {
                                    Thread.sleep(500);
                                    sendCommand(device, "true");
                                }
                            });
                            thread.start();
                            //return CommonUtil.successJson();
                            return "success";
                        } else {
                            return ErrorEnum.E_100025.getErrorCode();
                            //return CommonUtil.errorJson(ErrorEnum.E_100025);
                        }
                    }
                }

            }
        }
        return "success";
    }

    /**
     * 开门 自研硬件方案
     * @param tDeviceDto
     */
    @Override
    public String openDoorProg1(TDeviceDto tDeviceDto) throws Exception {
        logger.info("openDoor:" + tDeviceDto.toString());
        //根据订单Id获取订单信息
        TShareOrder tShareOrder = tShareOrderMapper.selectById(tDeviceDto.getOrderId());
        if (tShareOrder != null && tShareOrder.getOrderStatus() > 3 && !tDeviceDto.isAdmin()) {
            return ErrorEnum.E_100024.getErrorCode();
        }
        logger.info("tShareOrder:" + tShareOrder.toString());
        return "success";
        // 根据设备Id获取设备信息
//        TDevice device = tDeviceMapper.selectById(tDeviceDto.getSwitchid());
//        TDevice device = getPowerDeviceByStoreRoomIdOrStoreId(tShareOrder.getStoreId(), tShareOrder.getStoreRoomId(), 5);
//        if(device!=null){
//
//            logger.info("device.getDeviceType():" + device.getDeviceType());
//            // 表示用通通锁
//            if(device.getDeviceType()==5){
//
//                Boolean result = RequestTtlockUtils.executeUnlock(device.getDeviceNo());
//                if(result){
//                    return "success";
//                }
//
//            }else{
//
//                Boolean res = sendCommand(device, 2, 1);
//                if (res) {
//                    return "success";
//                } else {
//                    return ErrorEnum.E_100025.getErrorCode();
//                }
//
//            }
//        }else{
//
//            return ErrorEnum.E_100030.getErrorCode();
//        }
//        return ErrorEnum.E_100030.getErrorCode();

    }

    /**
     * 开门
     * @param tDeviceDto
     */
    @Override
    public String openDoor(TDeviceDto tDeviceDto) throws Exception {
        logger.info("openDoor:" + tDeviceDto.toString());
        //根据订单Id获取订单信息
        TShareOrder tShareOrder = tShareOrderMapper.selectById(tDeviceDto.getOrderId());
        if (tShareOrder != null && tShareOrder.getOrderStatus() > 3 && !tDeviceDto.isAdmin()) {
            return ErrorEnum.E_100024.getErrorCode();
        }
        logger.info("tShareOrder:" + tShareOrder.toString());
        // 根据设备Id获取设备信息
//        TDevice device = tDeviceMapper.selectById(tDeviceDto.getSwitchid());
        TDevice device = getPowerDeviceByStoreRoomIdOrStoreId(tShareOrder.getStoreId(), tShareOrder.getStoreRoomId(), 2);

        if(device!=null){
            logger.info("device:" + device.getDeviceNo() + "," + device.getMacAddr());

            // 表示用通通锁
            if(device.getDeviceType()==5){

                Boolean result = RequestTtlockUtils.executeUnlock(device.getDeviceNo());
                if(result){
                    return "success";
                }

            }else{

                if (sendCommand(device, "false")) {
                    Thread thread = new Thread(new Runnable() {
                        @SneakyThrows
                        @Override
                        public void run() {
                            Thread.sleep(500);
                            sendCommand(device, "true");
                        }
                    });
                    thread.start();
                    //return CommonUtil.successJson();
                    return "success";
                } else {
                    return ErrorEnum.E_100025.getErrorCode();
                    //return CommonUtil.errorJson(ErrorEnum.E_100025);
                }
            }

        }else{

            return ErrorEnum.E_100030.getErrorCode();
        }
        return ErrorEnum.E_100030.getErrorCode();
    }

    //自研硬件方案,开门锁
    public Boolean sendCommand(TDevice device, Integer commandType, Integer switchFlag) {
        try {
            List relayList = new ArrayList<>();
            PubMsg.sendCommand(device.getMacAddr(), commandType, switchFlag, "",device.getIsSub(),relayList,"");
            return true;
        } catch (MqttException exception) {
            log.info("自研硬件方案,开门锁失败 message:{},reasonCode:{}", exception.getMessage(), exception.getReasonCode());
            return false;
        }

    }

    /**
     * 发送指令给硬件
     * @param device
     * @param command
     * @return //return true; // 演示暂时直接返回true
     */
    public Boolean sendCommand(TDevice device, String command) {
        logger.info("====sendCommand====");

        Date date = new Date();
        String t = String.valueOf(date.getTime());
        Map<String, String> headerParam = new HashMap<>();
        String accessToken = TokenCache.getAccessTokenCache(tuyaClientId);
        headerParam.put("client_id", tuyaClientId);
        headerParam.put("access_token", accessToken);
        logger.info("sendCommand tuyaClientId ==>{}", tuyaClientId);
        logger.info("sendCommand accessToken ==>{}", accessToken);
        logger.info("sendCommand tuyaClientSecret ==>{}", tuyaClientSecret);
        try {
            if ("true".equals(command)) {
                Thread.sleep(1000);
            }
            headerParam.put("sign", SignUtil.HMACSHA256(tuyaClientId + accessToken + t, tuyaClientSecret));
        } catch (Exception e) {
            //logger.error("sign fail -> {}", e);
        }
        headerParam.put("t", t);
        headerParam.put("sign_method", "HMAC-SHA256");
        headerParam.put("Content-Type", "application/json");
        //String jsonParamStr = "{\"commands\":[{\"code\": \"" + device.getMacAddr() + "\",\"value\":" + command + "}]}";
        String switch_1 = "switch_1";
        String jsonParamStr = "{\"commands\":[{\"code\": \"" + switch_1 + "\",\"value\":" + command + "}]}";
        logger.info("sendCommand jsonParamStr ==>{}", jsonParamStr);
        Gson gson = new Gson();
        String busPath = "/v1.0/iot-03/devices/" + device.getDeviceNo() + "/commands";
        //execute(String accessToken, String path, String method, String body, Map<String, String> customHeaders)
        Object result = RequestSignUtils.execute(accessToken, busPath, "POST", jsonParamStr, new HashMap<>());
        String res = gson.toJson(result);
        logger.info("sendCommand res ==>{}", res);
        if (StringUtils.isEmpty(res)) {
            return false;
        }

        TDeviceLog deviceLog = new TDeviceLog();
        deviceLog.setDeviceNo(device.getDeviceNo());
        deviceLog.setCreateTime(new Date());
        // 通电
        deviceLog.setEvent((short) 1);
        deviceLog.setRemark("开门-" + command + ";结果：" + res);
        tDeviceLogMapper.insert(deviceLog);
        JSONObject resJson = JSONObject.parseObject(res);
        if (resJson.getBoolean("success")) {
            if (resJson.getBoolean("result")) {
                return true;
            } else {
                return false;
            }
        } else {

            String msg = resJson.getString("msg");
            if ("token invalid".equals(msg)) {
                log.info("tuya_token invalid:{}", msg);
                log.info("invalid_token:{}", TokenCache.getAccessTokenCache(tuyaClientId));
                // 重新获取tuya token
                getTuyaAccessToken();
                log.info("重新获取 tuya_token complete:{}", TokenCache.getAccessTokenCache(tuyaClientId));
                // 重新执行开门指令
                log.info("重新执行开门指令:{}", "sendCommand");
                return sendCommand1(device, command);
            }

            return false;
        }
    }

    /**
     * 发送指令给硬件
     * @param device
     * @param command
     * @return //return true; // 演示暂时直接返回true
     */
    public Boolean sendCommand1(TDevice device, String command) {
        logger.info("====sendCommand====");

        Date date = new Date();
        String t = String.valueOf(date.getTime());
        Map<String, String> headerParam = new HashMap<>();
        String accessToken = TokenCache.getAccessTokenCache(tuyaClientId);
        headerParam.put("client_id", tuyaClientId);
        headerParam.put("access_token", accessToken);
        logger.info("sendCommand tuyaClientId ==>{}", tuyaClientId);
        logger.info("sendCommand accessToken ==>{}", accessToken);
        logger.info("sendCommand tuyaClientSecret ==>{}", tuyaClientSecret);
        try {
            if ("true".equals(command)) {
                Thread.sleep(1000);
            }
            headerParam.put("sign", SignUtil.HMACSHA256(tuyaClientId + accessToken + t, tuyaClientSecret));
        } catch (Exception e) {
            //logger.error("sign fail -> {}", e);
        }
        headerParam.put("t", t);
        headerParam.put("sign_method", "HMAC-SHA256");
        headerParam.put("Content-Type", "application/json");
        //String jsonParamStr = "{\"commands\":[{\"code\": \"" + device.getMacAddr() + "\",\"value\":" + command + "}]}";
        String switch_1 = "switch_1";
        String jsonParamStr = "{\"commands\":[{\"code\": \"" + switch_1 + "\",\"value\":" + command + "}]}";
        logger.info("sendCommand jsonParamStr ==>{}", jsonParamStr);
        Gson gson = new Gson();
        String busPath = "/v1.0/iot-03/devices/" + device.getDeviceNo() + "/commands";
        //execute(String accessToken, String path, String method, String body, Map<String, String> customHeaders)
        Object result = RequestSignUtils.execute(accessToken, busPath, "POST", jsonParamStr, new HashMap<>());
        String res = gson.toJson(result);
        logger.info("sendCommand res ==>{}", res);
        if (StringUtils.isEmpty(res)) {
            return false;
        }

        TDeviceLog deviceLog = new TDeviceLog();
        deviceLog.setDeviceNo(device.getDeviceNo());
        deviceLog.setCreateTime(new Date());
        // 通电
        deviceLog.setEvent((short) 1);
        deviceLog.setRemark("开门-" + command + ";结果：" + res);
        tDeviceLogMapper.insert(deviceLog);
        JSONObject resJson = JSONObject.parseObject(res);
        if (resJson.getBoolean("success")) {
            if (resJson.getBoolean("result")) {
                return true;
            } else {
                return false;
            }
        } else {

            String msg = resJson.getString("msg");
            if ("token invalid".equals(msg)) {
                log.info("开锁失败");
                return false;
            }

            return false;
        }
    }

    private void getTuyaAccessToken() {
        String getTokenPath = "/v1.0/token?grant_type=1";
        Object res = RequestSignUtils.execute(getTokenPath, "GET", "", new HashMap<>());
        Gson gson = new Gson();
        String str = gson.toJson(res);
        JSONObject resJson = JSONObject.parseObject(str);
        if (resJson.getBoolean("success")) {
            JSONObject resultJson = resJson.getJSONObject("result");
            TokenCache.setAccessTokenCache(tuyaClientId, resultJson.getString("access_token"));
            TokenCache.setRefreshTokenCache(tuyaClientId, resultJson.getString("refresh_token"));
            log.info("Runner -> get token success!");
        } else {
            log.error("Runner -> get token error! res={}", res);
        }
    }

    @Override
    public TDevice getPowerDeviceByStoreRoomIdOrStoreId(Integer storeId, Integer storeRoomId, Integer deviceType) {
        LambdaQueryWrapper<TDevice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TDevice::getStatus, 1).eq(TDevice::getDeviceStatus, 1);
        wrapper.eq(TDevice::getStoreId, storeId);
        wrapper.eq(TDevice::getStoreRoomId, storeRoomId);
        wrapper.eq(TDevice::getDeviceType, deviceType);
        List<TDevice> devices = baseMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(devices)) {
            return devices.get(0);
        }
        return null;
    }
}
